commonlibsse_ng\re\p/
PlayerCamera.rs

1mod camera_state;
2mod runtime_data;
3mod runtime_data2;
4
5pub use self::camera_state::{
6    CameraState, CameraStateSE, CameraStateSE_CEnum, CameraStateVR, CameraStateVR_CEnum,
7};
8pub use self::runtime_data::{RUNTIME_DATA, Unk120, VR_RUNTIME_DATA};
9pub use self::runtime_data2::RUNTIME_DATA2;
10
11use crate::re::BSPointerHandle::ActorHandle;
12use crate::re::TESCamera::{TESCamera, TESCameraVtbl};
13use crate::re::offsets_rtti::RTTI_PlayerCamera;
14use crate::re::offsets_vtable::VTABLE_PlayerCamera;
15use crate::rel::id::VariantID;
16use crate::rel::module::is_vr;
17use crate::rel::relocation::{RelocationError, relocate_member, relocate_member_mut};
18
19#[repr(C)]
20#[derive(Debug, Clone, PartialEq)]
21pub struct PlayerCamera {
22    pub __base: TESCamera,         // 0x00
23    pub pad39: u8,                 // 0x39
24    pub pad3A: u16,                // 0x3A
25    pub cameraTarget: ActorHandle, // 0x3C
26}
27const _: () = assert!(std::mem::size_of::<PlayerCamera>() == 0x40);
28
29/// Simplify with macros due to the large amount of RUNTIME data.
30macro_rules! define_runtime_getters {
31    (
32        $( {
33            fn_name: $getter:ident,
34            fn_name_mut: $getter_mut:ident,
35            type: $data_type:ty,
36            se_ae_offset: $se_ae_offset:expr,
37            vr_offset: $vr_offset:expr
38        } ),* $(,)?
39    ) => {
40        $(
41            /// Gets fields whose offset is determined at runtime.
42            ///
43            /// # Errors
44            /// This function may return an error if the module's runtime is not available or if any error occurs while fetching the runtime state.
45            /// Specifically, it calls `ModuleState::map_active`, which could result in an error.
46            #[inline]
47            pub fn $getter(&self) -> Result<&$data_type, RelocationError> {
48                relocate_member(self, $se_ae_offset, $vr_offset)
49            }
50
51            /// Gets mutable fields whose offset is determined at runtime.
52            ///
53            /// # Errors
54            /// This function may return an error if the module's runtime is not available or if any error occurs while fetching the runtime state.
55            /// Specifically, it calls `ModuleState::map_active_mut`, which could result in an error.
56            #[inline]
57            pub fn $getter_mut(&mut self) -> Result<&mut $data_type, RelocationError> {
58                relocate_member_mut(self, $se_ae_offset, $vr_offset)
59            }
60        )*
61    };
62}
63
64impl PlayerCamera {
65    /// Address & offset of the runtime type information (RTTI) identifier.
66    pub const RTTI: VariantID = RTTI_PlayerCamera;
67
68    /// Address & offset of the virtual function table.
69    pub const VTABLE: [VariantID; 1] = VTABLE_PlayerCamera;
70
71    /// Returns the singleton instance of `Self`.
72    #[commonlibsse_ng_derive_internal::relocate(
73        cast_as = "*mut *mut PlayerCamera",
74        default = "None",
75        deref_once,
76        id(se = 514642, ae = 400802)
77    )]
78    pub fn get_singleton() -> Option<&'static PlayerCamera> {
79        |deref_type: DerefType| unsafe { deref_type.as_ref() }
80    }
81
82    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 49858, ae_id = 50790)]
83    #[inline]
84    pub fn force_first_person(&mut self) -> bool {
85        if is_vr() {
86            return false;
87        }
88    }
89
90    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 49863, ae_id = 50796)]
91    #[inline]
92    pub fn force_third_person(&mut self) -> bool {
93        if is_vr() {
94            return false;
95        }
96    }
97
98    #[inline]
99    pub fn is_in_bleedout_mode(&self) -> bool {
100        let is_vr = is_vr();
101        let state = if is_vr {
102            CameraStateVR::VRBleedout.to_state()
103        } else {
104            CameraStateSE::Bleedout.to_state()
105        };
106        self.q_camera_equals(state, is_vr)
107    }
108
109    #[inline]
110    pub fn is_in_first_person(&self) -> bool {
111        self.q_camera_equals(CameraStateSE::FirstPerson.to_state(), is_vr())
112    }
113
114    #[inline]
115    pub fn is_in_free_camera_mode(&self) -> bool {
116        self.q_camera_equals(CameraStateSE::Free.to_state(), is_vr())
117    }
118
119    #[inline]
120    pub fn is_in_third_person(&self) -> bool {
121        let is_vr = is_vr();
122        let state = if is_vr {
123            CameraStateVR::VRThirdPerson.to_state()
124        } else {
125            CameraStateSE::ThirdPerson.to_state()
126        };
127        self.q_camera_equals(state, is_vr)
128    }
129
130    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 49947, ae_id = 50880)]
131    #[inline]
132    pub fn push_camera_state(&mut self, state: CameraState) {}
133
134    #[inline]
135    pub fn q_camera_equals(&self, camera_state: CameraState, is_vr: bool) -> bool {
136        if self.__base.currentState.is_null() {
137            return false;
138        }
139
140        if is_vr {
141            match self.get_vr_runtime_data() {
142                Ok(runtime_data) => {
143                    if let Some(state_index) = camera_state.as_vr() {
144                        return !runtime_data.cameraStates[state_index as usize].is_null();
145                    };
146                    #[cfg(feature = "tracing")]
147                    tracing::warn!(
148                        "CameraState index for VR is 0..=13 is expected, but got `{}`.",
149                        camera_state.0
150                    );
151                }
152                Err(_err) => {
153                    #[cfg(feature = "tracing")]
154                    tracing::error!("{_err}");
155                }
156            }
157            return false;
158        }
159
160        // SE, AE
161        match self.get_runtime_data() {
162            Ok(runtime_data) => {
163                if let Some(state_index) = camera_state.as_se() {
164                    return !runtime_data.cameraStates[state_index as usize].is_null();
165                }
166                #[cfg(feature = "tracing")]
167                tracing::warn!(
168                    "CameraState index for SE/AE is 0..=12 is expected, but got `{}`.",
169                    camera_state.0
170                );
171            }
172            Err(_err) => {
173                #[cfg(feature = "tracing")]
174                tracing::error!("{_err}");
175            }
176        }
177        false
178    }
179
180    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 49876, ae_id = 50809)]
181    #[inline]
182    pub fn toggle_free_camera_mode(&mut self, freeze_time: bool) {}
183
184    #[commonlibsse_ng_derive_internal::relocate_fn(se_id = 49908, ae_id = 50841)]
185    #[inline]
186    pub fn update_third_person(&mut self, weapon_drawn: bool) {}
187
188    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
189    // Runtime data(The offset is determined at runtime, and the field is accessed via a method.)
190
191    define_runtime_getters! {
192        {
193            fn_name: get_runtime_data,
194            fn_name_mut: get_runtime_data_mut,
195            type: VR_RUNTIME_DATA,
196            se_ae_offset: 0x40,
197            vr_offset: 0
198        },
199        {
200            fn_name: get_runtime_data2,
201            fn_name_mut: get_runtime_data2_mut,
202            type: RUNTIME_DATA2,
203            se_ae_offset: 0x13C,
204            vr_offset: 0x158
205        },
206        {
207            fn_name: get_vr_runtime_data,
208            fn_name_mut: get_vr_runtime_data_mut,
209            type: VR_RUNTIME_DATA,
210            se_ae_offset: 0x0,
211            vr_offset: 0x40
212        },
213    }
214}
215
216#[repr(C)]
217#[derive(Debug)]
218pub struct PlayerCameraVtbl {
219    pub __base: TESCameraVtbl, // 0x00
220}
221const _: () = {
222    const VFUNC_COUNT: usize = 0x3;
223
224    const EXPECTED_SIZE: usize = VFUNC_COUNT * core::mem::size_of::<usize>();
225    assert!(core::mem::size_of::<PlayerCameraVtbl>() == EXPECTED_SIZE);
226};